package com.zqweb.gulimall.order.config;

import com.rabbitmq.client.Channel;
import com.zqweb.gulimall.order.entity.OrderEntity;
import com.zqweb.gulimall.order.enums.OrderStatusEnum;
import com.zqweb.gulimall.order.service.OrderService;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


@Configuration
// RabbitMQ相关组件（交换机、队列、Binding）的构建
public class MyRabbitComponentBuildConfig {
    @Autowired
    private OrderService orderService;

    // 监听超时后关单队列接收到的关单请求信息
    @RabbitListener(queues = {"order.release.order.queue"})
    public void closeOrderHandle(OrderEntity orderEntity, Message message, Channel channel) throws IOException {
        System.out.printf("用户下单后超时未支付，现将订单号为%s的订单进行关单处理！\n",orderEntity.getOrderSn());
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            orderService.closeOrderHandle(orderEntity);
            // 手动进行消息的ack
            channel.basicAck(deliveryTag,false);// 不进行批量ack
        } catch (Exception e) {
            channel.basicReject(deliveryTag,true);
        }
    }


    /*
        通过@Bean方式将RabbitMQ的相关组件声明并注入到容器中，便会触发RabbitMQ的AmqpAdmin自动将这些组件
        创建到MQ的Broker消息代理服务器上。但是，创建完毕后，是无法再通过修改构建的代码来实现组件相关属性参数的更改！
        必须通过先delete，再来调用、注入、创建！
     */
    @Bean
    // 构建订单生成后的延时队列
    public Queue buildOrderDelayQueue(){
        // String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments
        Map<String, Object> args = new HashMap<>();// Map是一个抽象接口，不能直接实例化
        args.put("x-dead-letter-exchange","order-event-exchange");
        args.put("x-dead-letter-routing-key","order.release.order");
        args.put("x-message-ttl",60000);// 1min

        return new Queue("order.delay.queue",true,false,false,args);
    }
    @Bean
    // 构建订单超时后的关单队列
    public Queue buildOrderReleaseQueue(){
        return new Queue("order.release.order.queue",true,false,false);
    }
    @Bean
    // 构建订单下单时或要关单时的事件型交换机（是Topic类型）
    public Exchange buildOrderEventExchange(){
        // String name, boolean durable, boolean autoDelete, Map<String, Object> arguments
        return new TopicExchange("order-event-exchange",true,false);
    }
    @Bean
    // 构建交换机到生成订单后的延时队列的Binding关联
    public Binding buildBindingToOrderDelayQueue(){
        // String destination, Binding.DestinationType destinationType, String exchange, String routingKey, @Nullable Map<String, Object> arguments
        return new Binding("order.delay.queue",Binding.DestinationType.QUEUE,"order-event-exchange","order.create.order",null);
    }
    @Bean
    // 构建交换机到超时后的关单队列的Binding关联
    public Binding buildBindingToOrderReleaseQueue(){
        return new Binding("order.release.order.queue", Binding.DestinationType.QUEUE,"order-event-exchange","order.release.order",null);
    }
    @Bean
    // 构建交换机到超时后的库存解锁队列的Binding关联
    public Binding buildBindingToStockReleaseQueue(){
        return new Binding("stock.release.stock.queue", Binding.DestinationType.QUEUE,"order-event-exchange","order.release.other.#",null);
    }
    @Bean
    // 构建秒杀单队列
    public Queue buildOrderSeckillQueue(){
        return new Queue("order.seckill.order.queue",true,false,false);
    }
    @Bean
    // 构建交换机到秒杀单队列的Binding关联
    public Binding buildBindingToOrderSeckillQueue(){
        return new Binding("order.seckill.order.queue", Binding.DestinationType.QUEUE,"order-event-exchange","order.seckill.order",null);
    }

}
